package com.dx.chat.server;

import com.dx.chat.util.AdressUtil;
import com.dx.chat.util.AlertUtil;
import com.dx.chat.util.ByteUtil;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * Description: 服务器服务端
 *
 * @author rockstarsteve
 * @version 1.0
 * @copyright Copyright (c) 电信
 * @since 2023/9/8
 */
@Slf4j
public class ServerService {

    ServerSocket serverSocket = null;

    /**
     * 启动服务
     *
     * @param serverInfoBean
     */
    public void startServer(ServerInfoBean serverInfoBean) {
        if (serverInfoBean.getIp() == null || "".equals(serverInfoBean.getIp())) {
            AlertUtil.alertWarn("提示", "服务器暂时无法获取到ip进行启动！");
            return;
        }
        if (serverInfoBean.getPort() == null || "".equals(serverInfoBean.getPort()) || !AdressUtil.isPort(serverInfoBean.getPort())) {
            AlertUtil.alertWarn("提示", "端口错误，请检查！");
            return;
        }
        // 创建服务器
        if (serverSocket != null) {
            AlertUtil.alertInfo("提示", "服务已经启动了！");
            return;
        }

        try {
            serverSocket = new ServerSocket(Integer.parseInt(serverInfoBean.getPort()));
        } catch (Exception ex) {
            log.error("创建服务失败：{}", ex);
        }
        serverInfoBean.setServerSocket(serverSocket);
        serverInfoBean.setChatInfoString(serverInfoBean.getChatInfoString() + "服务已启动，等待客户端连接...\n");
        new ServerThread(serverInfoBean).start();
    }

    /**
     * 发送文件
     * <h1>>规则</h1>
     * <p1>4位ip位 1位内容标识位 4位头部长度位 1位文件开始标识位 文件名称位  文件内容开始 （1位内容标识位：0：文本，1：文件；1位文件开始标识位:0：开始，1：中间部分）</p>
     * <p1>4位ip位 1位内容标识位 4位头部长度位 1位文件开始标识位 文件名称位 文件内容中间</p>
     * <p1>4位ip位 1位内容标识位 4位头部长度位 1位文件开始标识位 文件名称位 文件内容后面</p>
     *
     * @param serverInfoBean
     */
    public void sendFile(ServerInfoBean serverInfoBean) {
        if (serverInfoBean.getServerSocket() == null) {
            AlertUtil.alertInfo("提示", "还未启动服务！");
            return;
        }
        Map<String, Socket> ipSocketMap = serverInfoBean.getIpSocketMap();
        if (ipSocketMap.size() == 0) {
            AlertUtil.alertInfo("提示", "暂无活动的客户端！");
            return;
        }
        try {
            for (Map.Entry<String, Socket> ipSocket : ipSocketMap.entrySet()) {
                Socket socket = ipSocket.getValue();
                File file = new File(serverInfoBean.getFilePath());
                String fileName = file.getName();
                byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);
                int headLength = 10 + fileNameBytes.length;
                OutputStream outputStream = socket.getOutputStream();
                FileInputStream fileInputStream = new FileInputStream(file);
                //1.先把ip和头写过去
                byte[] addresByte = socket.getInetAddress().getAddress();
                //2.然后再把文件写过去
                int len = 0;
                byte[] fileBytes = new byte[1024 - headLength];
                boolean startFlag = true;
                while ((len = fileInputStream.read(fileBytes)) != -1) {
                    byte[] newByteArray = ByteUtil.reviseArray(fileBytes, headLength);
                    if (startFlag) {
                        newByteArray[9] = 0;
                        String localIpAddr = InetAddress.getLocalHost().getHostAddress();
                        serverInfoBean.setChatInfoString(serverInfoBean.getChatInfoString() + "服务端(" + localIpAddr + ")：正在发送\"" + fileName + "\"文件！\n");
                        startFlag = false;
                    } else {
                        newByteArray[9] = 1;
                    }
                    newByteArray[0] = addresByte[0];
                    newByteArray[1] = addresByte[1];
                    newByteArray[2] = addresByte[2];
                    newByteArray[3] = addresByte[3];
                    newByteArray[4] = 1;
                    //4位头部长度内容添加
                    byte[] headLengthBytes = ByteUtil.intToBytes(headLength);
                    for (int i = 0; i < headLengthBytes.length; i++) {
                        newByteArray[i + 5] = headLengthBytes[i];
                    }
                    //文件名称内容添加
                    for (int i = 0; i < fileNameBytes.length; i++) {
                        newByteArray[i + 10] = fileNameBytes[i];
                    }
                    outputStream.write(newByteArray, 0, len + headLength);
                }
                outputStream.flush();
                serverInfoBean.setFilePath("");
                serverInfoBean.setChatInfoString(serverInfoBean.getChatInfoString() + "服务端(" + serverInfoBean.getIp() + ")：发送\"" + fileName + "\"文件成功！\n");
            }
        } catch (Exception ex) {
            log.error("发送文件失败：{}", ex);
        }
    }

    /**
     * 发送消息
     *
     * @param serverInfoBean
     */
    public void sendMsg(ServerInfoBean serverInfoBean) {
        if (serverInfoBean.getServerSocket() == null) {
            AlertUtil.alertInfo("提示", "服务还未启动！");
            return;
        }
        Map<String, Socket> ipSocketMap = serverInfoBean.getIpSocketMap();
        if (ipSocketMap.size() == 0) {
            AlertUtil.alertInfo("提示", "暂无活动的客户端！");
            return;
        }

        String sendMsg = serverInfoBean.getSendMsg();
        if (sendMsg.length() > 300) {
            AlertUtil.alertInfo("提示", "暂无法发送超过300个字的文字内容！");
            return;
        }
        try {
            for (Map.Entry<String, Socket> ipSocke : ipSocketMap.entrySet()) {
                Socket socket = ipSocke.getValue();
                OutputStream outputStream = socket.getOutputStream();
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
                // 获取文本框内容
                if (sendMsg == null || "".equals(sendMsg)) {
                    return;
                }
                byte[] inputBytes = sendMsg.getBytes(StandardCharsets.UTF_8);
                byte[] sendBytes = new byte[inputBytes.length + 5];
                byte[] addresByte = socket.getInetAddress().getAddress();
                sendBytes[0] = addresByte[0];
                sendBytes[1] = addresByte[1];
                sendBytes[2] = addresByte[2];
                sendBytes[3] = addresByte[3];
                sendBytes[4] = 0;
                for (int i = 0; i < inputBytes.length; i++) {
                    sendBytes[i + 5] = inputBytes[i];
                }
                bufferedOutputStream.write(sendBytes);
                bufferedOutputStream.flush();
                serverInfoBean.setChatInfoString(serverInfoBean.getChatInfoString() + "服务器(" + serverInfoBean.getIp() + ")：" + sendMsg + "\n");
                serverInfoBean.setSendMsg("");
            }
        } catch (Exception ex) {
            log.error("发送消息失败：{}", ex);
        }
    }

    /**
     * 选择文件
     *
     * @param serverInfoBean
     * @param body
     */
    public void chooseFile(ServerInfoBean serverInfoBean, BorderPane body) {
        Stage stage = (Stage) body.getScene().getWindow();
        FileChooser fileChooser = new FileChooser();
        File file = fileChooser.showOpenDialog(stage);
        if (file != null && file.exists()) {
            serverInfoBean.setFilePath(file.getAbsolutePath());
        }
    }
}
